// xlsx 模块中文API封装 - 完整版本
const xlsx = require('xlsx');
const fs = require('fs');
const path = require('path');

/**
 * 从Excel文件读取数据
 * @param {string} 文件路径 - Excel文件路径
 * @param {Object} 选项 - 读取选项
 * @returns {Object} 工作簿对象
 */
function 读取Excel文件(文件路径, 选项 = {}) {
  if (!fs.existsSync(文件路径)) {
    throw new Error(`文件不存在: ${文件路径}`);
  }
  
  try {
    return xlsx.readFile(文件路径, 选项);
  } catch (错误) {
    throw new Error(`读取Excel文件失败: ${错误.message}`);
  }
}

/**
 * 从内存数据读取Excel
 * @param {Buffer|ArrayBuffer|Uint8Array|string} 数据 - Excel数据
 * @param {Object} 选项 - 读取选项
 * @returns {Object} 工作簿对象
 */
function 读取Excel数据(数据, 选项 = {}) {
  try {
    return xlsx.read(数据, 选项);
  } catch (错误) {
    throw new Error(`读取Excel数据失败: ${错误.message}`);
  }
}

/**
 * 创建新的工作簿
 * @returns {Object} 新工作簿对象
 */
function 创建工作簿() {
  return xlsx.utils.book_new();
}

/**
 * 将工作簿保存到文件
 * @param {Object} 工作簿 - 工作簿对象
 * @param {string} 文件路径 - 保存路径
 * @param {Object} 选项 - 保存选项
 */
function 保存工作簿(工作簿, 文件路径, 选项 = {}) {
  try {
    // 确保目录存在
    const 目录 = path.dirname(文件路径);
    if (!fs.existsSync(目录)) {
      fs.mkdirSync(目录, { recursive: true });
    }
    
    xlsx.writeFile(工作簿, 文件路径, 选项);
  } catch (错误) {
    throw new Error(`保存Excel文件失败: ${错误.message}`);
  }
}

/**
 * 将工作簿转换为Buffer
 * @param {Object} 工作簿 - 工作簿对象
 * @param {Object} 选项 - 写入选项
 * @returns {Buffer} Excel文件Buffer
 */
function 工作簿转Buffer(工作簿, 选项 = {}) {
  try {
    选项.type = 选项.type || 'buffer';
    选项.bookType = 选项.bookType || 'xlsx';
    return xlsx.write(工作簿, 选项);
  } catch (错误) {
    throw new Error(`转换工作簿到Buffer失败: ${错误.message}`);
  }
}

/**
 * 将JSON数据转换为工作表
 * @param {Array} 数据 - JSON数组数据
 * @param {Object} 选项 - 转换选项
 * @returns {Object} 工作表对象
 */
function JSON转工作表(数据, 选项 = {}) {
  try {
    return xlsx.utils.json_to_sheet(数据, 选项);
  } catch (错误) {
    throw new Error(`JSON转换为工作表失败: ${错误.message}`);
  }
}

/**
 * 将工作表转换为JSON数据
 * @param {Object} 工作表 - 工作表对象
 * @param {Object} 选项 - 转换选项
 * @returns {Array} JSON数组数据
 */
function 工作表转JSON(工作表, 选项 = {}) {
  try {
    // 默认选项，包含表头
    const 默认选项 = {
      header: 'A',
      raw: false,
      range: undefined,
      ...选项
    };
    
    return xlsx.utils.sheet_to_json(工作表, 默认选项);
  } catch (错误) {
    throw new Error(`工作表转换为JSON失败: ${错误.message}`);
  }
}

/**
 * 将数组数据转换为工作表
 * @param {Array} 数据 - 二维数组数据
 * @param {Object} 选项 - 转换选项
 * @returns {Object} 工作表对象
 */
function 数组转工作表(数据, 选项 = {}) {
  try {
    return xlsx.utils.aoa_to_sheet(数据, 选项);
  } catch (错误) {
    throw new Error(`数组转换为工作表失败: ${错误.message}`);
  }
}

/**
 * 将工作表转换为数组
 * @param {Object} 工作表 - 工作表对象
 * @param {Object} 选项 - 转换选项
 * @returns {Array} 二维数组数据
 */
function 工作表转数组(工作表, 选项 = {}) {
  try {
    return xlsx.utils.sheet_to_json(工作表, { header: 1, ...选项 });
  } catch (错误) {
    throw new Error(`工作表转换为数组失败: ${错误.message}`);
  }
}

/**
 * 获取工作簿中的所有工作表名称
 * @param {Object} 工作簿 - 工作簿对象
 * @returns {Array} 工作表名称数组
 */
function 获取工作表名称列表(工作簿) {
  return 工作簿.SheetNames || [];
}

/**
 * 根据名称获取工作表
 * @param {Object} 工作簿 - 工作簿对象
 * @param {string} 工作表名称 - 工作表名称
 * @returns {Object|null} 工作表对象或null
 */
function 获取工作表(工作簿, 工作表名称) {
  return 工作簿.Sheets[工作表名称] || null;
}

/**
 * 获取第一个工作表
 * @param {Object} 工作簿 - 工作簿对象
 * @returns {Object|null} 第一个工作表对象或null
 */
function 获取第一个工作表(工作簿) {
  const 工作表名称 = 获取工作表名称列表(工作簿)[0];
  return 工作表名称 ? 获取工作表(工作簿, 工作表名称) : null;
}

/**
 * 将工作表添加到工作簿
 * @param {Object} 工作簿 - 工作簿对象
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 工作表名称 - 工作表名称
 */
function 添加工作表到工作簿(工作簿, 工作表, 工作表名称) {
  try {
    xlsx.utils.book_append_sheet(工作簿, 工作表, 工作表名称);
  } catch (错误) {
    throw new Error(`添加工作表到工作簿失败: ${错误.message}`);
  }
}

/**
 * 创建工作表
 * @param {string} 单元格范围 - 例如 'A1:C3'
 * @param {Object} 单元格对象 - 单元格内容对象
 * @returns {Object} 工作表对象
 */
function 创建工作表(单元格范围 = '', 单元格对象 = {}) {
  try {
    return xlsx.utils.aoa_to_sheet([[]]);
  } catch (错误) {
    throw new Error(`创建工作表失败: ${错误.message}`);
  }
}

/**
 * 设置单元格值
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 单元格地址 - 例如 'A1'
 * @param {*} 值 - 单元格值
 * @param {Object} 单元格选项 - 单元格格式等选项
 */
function 设置单元格值(工作表, 单元格地址, 值, 单元格选项 = {}) {
  try {
    工作表[单元格地址] = {
      v: 值,
      ...单元格选项
    };
    
    // 如果是数值或日期，需要设置类型
    if (typeof 值 === 'number') {
      工作表[单元格地址].t = 'n';
    } else if (值 instanceof Date) {
      工作表[单元格地址].t = 'd';
    } else if (typeof 值 === 'boolean') {
      工作表[单元格地址].t = 'b';
    } else {
      工作表[单元格地址].t = 's';
    }
  } catch (错误) {
    throw new Error(`设置单元格值失败: ${错误.message}`);
  }
}

/**
 * 获取单元格值
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 单元格地址 - 例如 'A1'
 * @returns {*} 单元格值
 */
function 获取单元格值(工作表, 单元格地址) {
  try {
    const 单元格 = 工作表[单元格地址];
    if (!单元格) return null;
    return 单元格.v;
  } catch (错误) {
    throw new Error(`获取单元格值失败: ${错误.message}`);
  }
}

/**
 * 合并单元格
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 范围 - 合并范围，例如 'A1:C3'
 */
function 合并单元格(工作表, 范围) {
  try {
    if (!工作表['!merges']) {
      工作表['!merges'] = [];
    }
    
    // 解析范围字符串
    const 范围对象 = xlsx.utils.decode_range(范围);
    工作表['!merges'].push(范围对象);
  } catch (错误) {
    throw new Error(`合并单元格失败: ${错误.message}`);
  }
}

/**
 * 设置列宽
 * @param {Object} 工作表 - 工作表对象
 * @param {Array} 列宽数组 - 例如 [{ wch: 10 }, { wch: 20 }]
 */
function 设置列宽(工作表, 列宽数组) {
  try {
    工作表['!cols'] = 列宽数组;
  } catch (错误) {
    throw new Error(`设置列宽失败: ${错误.message}`);
  }
}

/**
 * 设置行高
 * @param {Object} 工作表 - 工作表对象
 * @param {Array} 行高数组 - 例如 [{ hpt: 20 }, { hpt: 30 }]
 */
function 设置行高(工作表, 行高数组) {
  try {
    工作表['!rows'] = 行高数组;
  } catch (错误) {
    throw new Error(`设置行高失败: ${错误.message}`);
  }
}

/**
 * 从HTML表格创建工作表
 * @param {string} html - HTML表格字符串
 * @param {Object} 选项 - 转换选项
 * @returns {Object} 工作表对象
 */
function HTML转工作表(html, 选项 = {}) {
  try {
    return xlsx.utils.table_to_sheet(html, 选项);
  } catch (错误) {
    throw new Error(`HTML转换为工作表失败: ${错误.message}`);
  }
}

/**
 * 将工作表转换为CSV字符串
 * @param {Object} 工作表 - 工作表对象
 * @param {Object} 选项 - 转换选项
 * @returns {string} CSV字符串
 */
function 工作表转CSV(工作表, 选项 = {}) {
  try {
    选项.type = 'string';
    return xlsx.utils.sheet_to_csv(工作表, 选项);
  } catch (错误) {
    throw new Error(`工作表转换为CSV失败: ${错误.message}`);
  }
}

/**
 * 将CSV字符串转换为工作表
 * @param {string} csv - CSV字符串
 * @param {Object} 选项 - 转换选项
 * @returns {Object} 工作表对象
 */
function CSV转工作表(csv, 选项 = {}) {
  try {
    return xlsx.utils.csv_to_sheet(csv, 选项);
  } catch (错误) {
    throw new Error(`CSV转换为工作表失败: ${错误.message}`);
  }
}

/**
 * 复制工作表
 * @param {Object} 工作簿 - 源工作簿
 * @param {string} 源工作表名称 - 源工作表名称
 * @param {string} 目标工作表名称 - 新工作表名称
 * @returns {Object} 新的工作表对象
 */
function 复制工作表(工作簿, 源工作表名称, 目标工作表名称) {
  try {
    const 源工作表 = 获取工作表(工作簿, 源工作表名称);
    if (!源工作表) {
      throw new Error(`源工作表不存在: ${源工作表名称}`);
    }
    
    const 新工作表 = JSON.parse(JSON.stringify(源工作表));
    添加工作表到工作簿(工作簿, 新工作表, 目标工作表名称);
    return 新工作表;
  } catch (错误) {
    throw new Error(`复制工作表失败: ${错误.message}`);
  }
}

/**
 * 删除工作表
 * @param {Object} 工作簿 - 工作簿对象
 * @param {string} 工作表名称 - 要删除的工作表名称
 * @returns {boolean} 是否删除成功
 */
function 删除工作表(工作簿, 工作表名称) {
  try {
    const 工作表索引 = 工作簿.SheetNames.indexOf(工作表名称);
    if (工作表索引 === -1) {
      return false;
    }
    
    工作簿.SheetNames.splice(工作表索引, 1);
    delete 工作簿.Sheets[工作表名称];
    return true;
  } catch (错误) {
    throw new Error(`删除工作表失败: ${错误.message}`);
  }
}

/**
 * 重命名工作表
 * @param {Object} 工作簿 - 工作簿对象
 * @param {string} 旧名称 - 旧工作表名称
 * @param {string} 新名称 - 新工作表名称
 * @returns {boolean} 是否重命名成功
 */
function 重命名工作表(工作簿, 旧名称, 新名称) {
  try {
    const 工作表索引 = 工作簿.SheetNames.indexOf(旧名称);
    if (工作表索引 === -1) {
      return false;
    }
    
    工作簿.SheetNames[工作表索引] = 新名称;
    工作簿.Sheets[新名称] = 工作簿.Sheets[旧名称];
    delete 工作簿.Sheets[旧名称];
    return true;
  } catch (错误) {
    throw new Error(`重命名工作表失败: ${错误.message}`);
  }
}

/**
 * 获取工作表范围
 * @param {Object} 工作表 - 工作表对象
 * @returns {Object|null} 范围对象或null
 */
function 获取工作表范围(工作表) {
  try {
    return 工作表['!ref'] ? xlsx.utils.decode_range(工作表['!ref']) : null;
  } catch (错误) {
    throw new Error(`获取工作表范围失败: ${错误.message}`);
  }
}

/**
 * 设置工作表范围
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 范围 - 范围字符串，例如 'A1:C10'
 */
function 设置工作表范围(工作表, 范围) {
  try {
    工作表['!ref'] = 范围;
  } catch (错误) {
    throw new Error(`设置工作表范围失败: ${错误.message}`);
  }
}

/**
 * 创建带有表头的工作表
 * @param {Array} 表头 - 表头数组
 * @param {Array} 数据 - 数据数组
 * @returns {Object} 工作表对象
 */
function 创建带表头工作表(表头, 数据) {
  try {
    // 创建包含表头的二维数组
    const 表格数据 = [表头];
    
    // 添加数据行
    数据.forEach(行数据 => {
      const 数据行 = 表头.map(列名 => 行数据[列名] || '');
      表格数据.push(数据行);
    });
    
    return 数组转工作表(表格数据);
  } catch (错误) {
    throw new Error(`创建带表头工作表失败: ${错误.message}`);
  }
}

/**
 * 批量读取Excel文件中的所有工作表
 * @param {string} 文件路径 - Excel文件路径
 * @returns {Object} 包含所有工作表数据的对象
 */
function 读取所有工作表(文件路径) {
  try {
    const 工作簿 = 读取Excel文件(文件路径);
    const 结果 = {};
    
    获取工作表名称列表(工作簿).forEach(工作表名称 => {
      const 工作表 = 获取工作表(工作簿, 工作表名称);
      结果[工作表名称] = 工作表转JSON(工作表);
    });
    
    return 结果;
  } catch (错误) {
    throw new Error(`批量读取工作表失败: ${错误.message}`);
  }
}

/**
 * 将多个JSON数据集保存到Excel文件
 * @param {Object} 数据集 - 数据集对象，格式: {sheet1: [...], sheet2: [...]}
 * @param {string} 文件路径 - 保存路径
 * @param {Object} 选项 - 保存选项
 */
function 保存多工作表Excel(数据集, 文件路径, 选项 = {}) {
  try {
    const 工作簿 = 创建工作簿();
    
    Object.keys(数据集).forEach(工作表名称 => {
      const 数据 = 数据集[工作表名称];
      const 工作表 = JSON转工作表(数据);
      添加工作表到工作簿(工作簿, 工作表, 工作表名称);
    });
    
    保存工作簿(工作簿, 文件路径, 选项);
  } catch (错误) {
    throw new Error(`保存多工作表Excel失败: ${错误.message}`);
  }
}

/**
 * 导出数据到Excel文件（简单版本）
 * @param {Array} 数据 - JSON数组数据
 * @param {string} 文件路径 - 保存路径
 * @param {string} 工作表名称 - 工作表名称
 */
function 导出到Excel(数据, 文件路径, 工作表名称 = 'Sheet1') {
  try {
    const 工作簿 = 创建工作簿();
    const 工作表 = JSON转工作表(数据);
    添加工作表到工作簿(工作簿, 工作表, 工作表名称);
    保存工作簿(工作簿, 文件路径);
  } catch (错误) {
    throw new Error(`导出到Excel失败: ${错误.message}`);
  }
}

/**
 * 从Excel文件导入数据（简单版本）
 * @param {string} 文件路径 - Excel文件路径
 * @param {string} 工作表名称 - 工作表名称，不指定则使用第一个
 * @returns {Array} JSON数组数据
 */
function 从Excel导入(文件路径, 工作表名称 = null) {
  try {
    const 工作簿 = 读取Excel文件(文件路径);
    let 工作表;
    
    if (工作表名称) {
      工作表 = 获取工作表(工作簿, 工作表名称);
      if (!工作表) {
        throw new Error(`工作表不存在: ${工作表名称}`);
      }
    } else {
      工作表 = 获取第一个工作表(工作簿);
      if (!工作表) {
        throw new Error('Excel文件中没有工作表');
      }
    }
    
    return 工作表转JSON(工作表);
  } catch (错误) {
    throw new Error(`从Excel导入失败: ${错误.message}`);
  }
}

/**
 * 检查文件是否为有效的Excel文件
 * @param {string} 文件路径 - 文件路径
 * @returns {boolean} 是否为有效Excel文件
 */
function 是有效Excel文件(文件路径) {
  try {
    if (!fs.existsSync(文件路径)) {
      return false;
    }
    
    const 文件扩展名 = path.extname(文件路径).toLowerCase();
    const 有效扩展名 = ['.xlsx', '.xlsm', '.xls', '.xlsb', '.xltx', '.xltm', '.xlam', '.xla'];
    
    if (!有效扩展名.includes(文件扩展名)) {
      return false;
    }
    
    // 尝试读取文件头来验证
    const 缓冲区 = Buffer.alloc(8);
    const fd = fs.openSync(文件路径, 'r');
    fs.readSync(fd, 缓冲区, 0, 8, 0);
    fs.closeSync(fd);
    
    // Excel文件的魔术数字
    const excelMagicNumbers = [
      [0x50, 0x4B, 0x03, 0x04], // XLSX, XLSM, XLTX, XLTM, XLSB, XLAM
      [0xD0, 0xCF, 0x11, 0xE0]  // XLS
    ];
    
    for (const magic of excelMagicNumbers) {
      let match = true;
      for (let i = 0; i < magic.length; i++) {
        if (缓冲区[i] !== magic[i]) {
          match = false;
          break;
        }
      }
      if (match) {
        return true;
      }
    }
    
    return false;
  } catch (错误) {
    return false;
  }
}

/**
 * 将Excel文件转换为其他格式
 * @param {string} 源文件路径 - 源Excel文件路径
 * @param {string} 目标文件路径 - 目标文件路径
 * @param {Object} 选项 - 转换选项
 */
function 转换Excel格式(源文件路径, 目标文件路径, 选项 = {}) {
  try {
    const 工作簿 = 读取Excel文件(源文件路径);
    const 目标扩展名 = path.extname(目标文件路径).toLowerCase().slice(1);
    
    保存工作簿(工作簿, 目标文件路径, {
      bookType: 目标扩展名,
      ...选项
    });
  } catch (错误) {
    throw new Error(`转换Excel格式失败: ${错误.message}`);
  }
}

/**
 * 获取Excel文件信息
 * @param {string} 文件路径 - Excel文件路径
 * @returns {Object} 文件信息对象
 */
function 获取Excel文件信息(文件路径) {
  try {
    const 工作簿 = 读取Excel文件(文件路径);
    const 工作表名称列表 = 获取工作表名称列表(工作簿);
    
    const 工作表信息 = {};
    工作表名称列表.forEach(工作表名称 => {
      const 工作表 = 获取工作表(工作簿, 工作表名称);
      const 数据 = 工作表转数组(工作表);
      工作表信息[工作表名称] = {
        行数: 数据.length,
        列数: 数据.length > 0 ? 数据[0].length : 0
      };
    });
    
    return {
      工作表数量: 工作表名称列表.length,
      工作表名称: 工作表名称列表,
      工作表信息: 工作表信息
    };
  } catch (错误) {
    throw new Error(`获取Excel文件信息失败: ${错误.message}`);
  }
}

/**
 * 获取单元格地址的行列索引
 * @param {string} 单元格地址 - 例如 'A1'
 * @returns {Object} 包含行索引和列索引的对象
 */
function 解析单元格地址(单元格地址) {
  try {
    return xlsx.utils.decode_cell(单元格地址);
  } catch (错误) {
    throw new Error(`解析单元格地址失败: ${错误.message}`);
  }
}

/**
 * 根据行列索引生成单元格地址
 * @param {number} 行索引 - 从0开始
 * @param {number} 列索引 - 从0开始
 * @returns {string} 单元格地址，例如 'A1'
 */
function 生成单元格地址(行索引, 列索引) {
  try {
    return xlsx.utils.encode_cell({ r: 行索引, c: 列索引 });
  } catch (错误) {
    throw new Error(`生成单元格地址失败: ${错误.message}`);
  }
}

/**
 * 解析范围字符串
 * @param {string} 范围字符串 - 例如 'A1:C3'
 * @returns {Object} 范围对象
 */
function 解析范围(范围字符串) {
  try {
    return xlsx.utils.decode_range(范围字符串);
  } catch (错误) {
    throw new Error(`解析范围失败: ${错误.message}`);
  }
}

/**
 * 生成范围字符串
 * @param {Object} 范围对象 - 包含s和e属性的对象
 * @returns {string} 范围字符串，例如 'A1:C3'
 */
function 生成范围(范围对象) {
  try {
    return xlsx.utils.encode_range(范围对象);
  } catch (错误) {
    throw new Error(`生成范围失败: ${错误.message}`);
  }
}

/**
 * 将工作表转换为TSV格式
 * @param {Object} 工作表 - 工作表对象
 * @param {Object} 选项 - 转换选项
 * @returns {string} TSV字符串
 */
function 工作表转TSV(工作表, 选项 = {}) {
  try {
    选项.type = 'string';
    return xlsx.utils.sheet_to_tsv(工作表, 选项);
  } catch (错误) {
    throw new Error(`工作表转换为TSV失败: ${错误.message}`);
  }
}

/**
 * 将TSV字符串转换为工作表
 * @param {string} tsv - TSV字符串
 * @param {Object} 选项 - 转换选项
 * @returns {Object} 工作表对象
 */
function TSV转工作表(tsv, 选项 = {}) {
  try {
    return xlsx.utils.tsv_to_sheet(tsv, 选项);
  } catch (错误) {
    throw new Error(`TSV转换为工作表失败: ${错误.message}`);
  }
}

/**
 * 将工作表转换为HTML
 * @param {Object} 工作表 - 工作表对象
 * @param {Object} 选项 - 转换选项
 * @returns {string} HTML字符串
 */
function 工作表转HTML(工作表, 选项 = {}) {
  try {
    选项.type = 'string';
    return xlsx.utils.sheet_to_html(工作表, 选项);
  } catch (错误) {
    throw new Error(`工作表转换为HTML失败: ${错误.message}`);
  }
}

/**
 * 获取工作表的列标题数组
 * @param {Object} 工作表 - 工作表对象
 * @returns {Array} 列标题数组
 */
function 获取列标题(工作表) {
  try {
    const 数组数据 = 工作表转数组(工作表);
    return 数组数据.length > 0 ? 数组数据[0] : [];
  } catch (错误) {
    throw new Error(`获取列标题失败: ${错误.message}`);
  }
}

/**
 * 创建共享字符串表
 * @param {Array} 字符串数组 - 要共享的字符串数组
 * @returns {Object} 共享字符串表对象
 */
function 创建共享字符串表(字符串数组) {
  try {
    return xlsx.utils.book_new_shared_strings(字符串数组);
  } catch (错误) {
    throw new Error(`创建共享字符串表失败: ${错误.message}`);
  }
}

/**
 * 克隆工作表
 * @param {Object} 工作表 - 要克隆的工作表
 * @returns {Object} 克隆的工作表
 */
function 克隆工作表(工作表) {
  try {
    return JSON.parse(JSON.stringify(工作表));
  } catch (错误) {
    throw new Error(`克隆工作表失败: ${错误.message}`);
  }
}

/**
 * 清除工作表内容
 * @param {Object} 工作表 - 要清除的工作表
 */
function 清除工作表内容(工作表) {
  try {
    // 保留合并单元格和列宽信息
    const 合并信息 = 工作表['!merges'];
    const 列宽信息 = 工作表['!cols'];
    const 行高信息 = 工作表['!rows'];
    const 范围信息 = 工作表['!ref'];
    
    // 创建新的空工作表
    const 新工作表 = xlsx.utils.aoa_to_sheet([[]]);
    
    // 恢复保存的信息
    if (合并信息) 新工作表['!merges'] = 合并信息;
    if (列宽信息) 新工作表['!cols'] = 列宽信息;
    if (行高信息) 新工作表['!rows'] = 行高信息;
    if (范围信息) 新工作表['!ref'] = 范围信息;
    
    // 复制回原工作表
    Object.keys(工作表).forEach(键 => {
      delete 工作表[键];
    });
    
    Object.keys(新工作表).forEach(键 => {
      工作表[键] = 新工作表[键];
    });
  } catch (错误) {
    throw new Error(`清除工作表内容失败: ${错误.message}`);
  }
}

/**
 * 插入行
 * @param {Object} 工作表 - 工作表对象
 * @param {number} 行号 - 要插入的行号（从1开始）
 * @param {Array} 数据 - 行数据
 */
function 插入行(工作表, 行号, 数据) {
  try {
    const 数组数据 = 工作表转数组(工作表);
    数组数据.splice(行号 - 1, 0, 数据);
    
    // 保留工作表属性
    const 合并信息 = 工作表['!merges'];
    const 列宽信息 = 工作表['!cols'];
    const 行高信息 = 工作表['!rows'];
    
    // 创建新工作表
    const 新工作表 = 数组转工作表(数组数据);
    
    // 恢复属性
    if (合并信息) 新工作表['!merges'] = 合并信息;
    if (列宽信息) 新工作表['!cols'] = 列宽信息;
    if (行高信息) 新工作表['!rows'] = 行高信息;
    
    // 复制回原工作表
    Object.keys(工作表).forEach(键 => {
      delete 工作表[键];
    });
    
    Object.keys(新工作表).forEach(键 => {
      工作表[键] = 新工作表[键];
    });
  } catch (错误) {
    throw new Error(`插入行失败: ${错误.message}`);
  }
}

/**
 * 删除行
 * @param {Object} 工作表 - 工作表对象
 * @param {number} 行号 - 要删除的行号（从1开始）
 * @param {number} 数量 - 要删除的行数
 */
function 删除行(工作表, 行号, 数量 = 1) {
  try {
    const 数组数据 = 工作表转数组(工作表);
    数组数据.splice(行号 - 1, 数量);
    
    // 保留工作表属性
    const 合并信息 = 工作表['!merges'];
    const 列宽信息 = 工作表['!cols'];
    const 行高信息 = 工作表['!rows'];
    
    // 创建新工作表
    const 新工作表 = 数组转工作表(数组数据);
    
    // 恢复属性
    if (合并信息) 新工作表['!merges'] = 合并信息;
    if (列宽信息) 新工作表['!cols'] = 列宽信息;
    if (行高信息) 新工作表['!rows'] = 行高信息;
    
    // 复制回原工作表
    Object.keys(工作表).forEach(键 => {
      delete 工作表[键];
    });
    
    Object.keys(新工作表).forEach(键 => {
      工作表[键] = 新工作表[键];
    });
  } catch (错误) {
    throw new Error(`删除行失败: ${错误.message}`);
  }
}

/**
 * 插入列
 * @param {Object} 工作表 - 工作表对象
 * @param {number} 列号 - 要插入的列号（从1开始）
 * @param {Array} 数据 - 列数据
 */
function 插入列(工作表, 列号, 数据) {
  try {
    const 数组数据 = 工作表转数组(工作表);
    
    // 确保数据长度足够
    while (数据.length < 数组数据.length) {
      数据.push('');
    }
    
    // 插入数据到每一行
    数组数据.forEach((行, 索引) => {
      行.splice(列号 - 1, 0, 数据[索引] || '');
    });
    
    // 保留工作表属性
    const 合并信息 = 工作表['!merges'];
    const 列宽信息 = 工作表['!cols'];
    const 行高信息 = 工作表['!rows'];
    
    // 创建新工作表
    const 新工作表 = 数组转工作表(数组数据);
    
    // 恢复属性
    if (合并信息) 新工作表['!merges'] = 合并信息;
    if (列宽信息) 新工作表['!cols'] = 列宽信息;
    if (行高信息) 新工作表['!rows'] = 行高信息;
    
    // 复制回原工作表
    Object.keys(工作表).forEach(键 => {
      delete 工作表[键];
    });
    
    Object.keys(新工作表).forEach(键 => {
      工作表[键] = 新工作表[键];
    });
  } catch (错误) {
    throw new Error(`插入列失败: ${错误.message}`);
  }
}

/**
 * 删除列
 * @param {Object} 工作表 - 工作表对象
 * @param {number} 列号 - 要删除的列号（从1开始）
 * @param {number} 数量 - 要删除的列数
 */
function 删除列(工作表, 列号, 数量 = 1) {
  try {
    const 数组数据 = 工作表转数组(工作表);
    
    // 从每一行删除指定列
    数组数据.forEach(行 => {
      行.splice(列号 - 1, 数量);
    });
    
    // 保留工作表属性
    const 合并信息 = 工作表['!merges'];
    const 列宽信息 = 工作表['!cols'];
    const 行高信息 = 工作表['!rows'];
    
    // 创建新工作表
    const 新工作表 = 数组转工作表(数组数据);
    
    // 恢复属性
    if (合并信息) 新工作表['!merges'] = 合并信息;
    if (列宽信息) 新工作表['!cols'] = 列宽信息;
    if (行高信息) 新工作表['!rows'] = 行高信息;
    
    // 复制回原工作表
    Object.keys(工作表).forEach(键 => {
      delete 工作表[键];
    });
    
    Object.keys(新工作表).forEach(键 => {
      工作表[键] = 新工作表[键];
    });
  } catch (错误) {
    throw new Error(`删除列失败: ${错误.message}`);
  }
}

/**
 * 查找单元格
 * @param {Object} 工作表 - 工作表对象
 * @param {*} 搜索值 - 要搜索的值
 * @returns {Array} 匹配的单元格地址数组
 */
function 查找单元格(工作表, 搜索值) {
  try {
    const 结果 = [];
    const 数组数据 = 工作表转数组(工作表);
    
    数组数据.forEach((行, 行索引) => {
      行.forEach((单元格值, 列索引) => {
        if (单元格值 === 搜索值) {
          结果.push(生成单元格地址(行索引, 列索引));
        }
      });
    });
    
    return 结果;
  } catch (错误) {
    throw new Error(`查找单元格失败: ${错误.message}`);
  }
}

/**
 * 设置单元格样式
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 单元格地址 - 单元格地址
 * @param {Object} 样式 - 样式对象
 */
function 设置单元格样式(工作表, 单元格地址, 样式) {
  try {
    if (!工作表[单元格地址]) {
      工作表[单元格地址] = { v: '' };
    }
    
    工作表[单元格地址].s = { ...(工作表[单元格地址].s || {}), ...样式 };
  } catch (错误) {
    throw new Error(`设置单元格样式失败: ${错误.message}`);
  }
}

/**
 * 获取工作表的使用区域
 * @param {Object} 工作表 - 工作表对象
 * @returns {Object} 区域对象
 */
function 获取使用区域(工作表) {
  try {
    return xlsx.utils.decode_range(xlsx.utils.encode_range(工作表['!ref'] || 'A1:A1'));
  } catch (错误) {
    throw new Error(`获取使用区域失败: ${错误.message}`);
  }
}

/**
 * 将数据追加到工作表末尾
 * @param {Object} 工作表 - 工作表对象
 * @param {Array} 数据 - 要追加的数据数组
 */
function 追加数据到工作表(工作表, 数据) {
  try {
    const 现有数据 = 工作表转数组(工作表);
    const 追加数据 = Array.isArray(data[0]) ? 数据 : data.map(item => Array.isArray(item) ? item : [item]);
    
    // 合并数据
    const 新数据 = [...现有数据, ...追加数据];
    
    // 保留工作表属性
    const 合并信息 = 工作表['!merges'];
    const 列宽信息 = 工作表['!cols'];
    const 行高信息 = 工作表['!rows'];
    
    // 创建新工作表
    const 新工作表 = 数组转工作表(新数据);
    
    // 恢复属性
    if (合并信息) 新工作表['!merges'] = 合并信息;
    if (列宽信息) 新工作表['!cols'] = 列宽信息;
    if (行高信息) 新工作表['!rows'] = 行高信息;
    
    // 复制回原工作表
    Object.keys(工作表).forEach(键 => {
      delete 工作表[键];
    });
    
    Object.keys(新工作表).forEach(键 => {
      工作表[键] = 新工作表[键];
    });
  } catch (错误) {
    throw new Error(`追加数据到工作表失败: ${错误.message}`);
  }
}

/**
 * 冻结窗格
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 单元格地址 - 冻结点，例如 'B2'
 */
function 冻结窗格(工作表, 单元格地址) {
  try {
    工作表['!freeze'] = 单元格地址;
  } catch (错误) {
    throw new Error(`冻结窗格失败: ${错误.message}`);
  }
}

/**
 * 自动调整列宽
 * @param {Object} 工作表 - 工作表对象
 */
function 自动调整列宽(工作表) {
  try {
    const 数组数据 = 工作表转数组(工作表);
    const 列宽 = [];
    
    // 计算每列的最大宽度
    if (数组数据.length > 0) {
      const 最大列数 = Math.max(...数组数据.map(行 => 行.length));
      
      for (let 列 = 0; 列 < 最大列数; 列++) {
        let 最大宽度 = 0;
        
        for (let 行 = 0; 行 < 数组数据.length; 行++) {
          if (数组数据[行][列]) {
            const 单元格值 = String(数组数据[行][列]);
            最大宽度 = Math.max(最大宽度, 单元格值.length);
          }
        }
        
        // 为中文等宽字符调整宽度，每两个英文字符宽度相当于一个中文字符
        const 调整后宽度 = Math.min(最大宽度 * 1.1 + 2, 50); // 限制最大宽度
        列宽.push({ wch: Math.ceil(调整后宽度) });
      }
    }
    
    设置列宽(工作表, 列宽);
  } catch (错误) {
    throw new Error(`自动调整列宽失败: ${错误.message}`);
  }
}

/**
 * 设置页眉
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 页眉内容 - 页眉文本
 */
function 设置页眉(工作表, 页眉内容) {
  try {
    if (!工作表['!header']) {
      工作表['!header'] = [];
    }
    工作表['!header'][0] = 页眉内容;
  } catch (错误) {
    throw new Error(`设置页眉失败: ${错误.message}`);
  }
}

/**
 * 设置页脚
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 页脚内容 - 页脚文本
 */
function 设置页脚(工作表, 页脚内容) {
  try {
    if (!工作表['!footer']) {
      工作表['!footer'] = [];
    }
    工作表['!footer'][0] = 页脚内容;
  } catch (错误) {
    throw new Error(`设置页脚失败: ${错误.message}`);
  }
}

/**
 * 隐藏行
 * @param {Object} 工作表 - 工作表对象
 * @param {number} 行号 - 要隐藏的行号（从1开始）
 */
function 隐藏行(工作表, 行号) {
  try {
    if (!工作表['!rows']) {
      工作表['!rows'] = [];
    }
    if (!工作表['!rows'][行号 - 1]) {
      工作表['!rows'][行号 - 1] = {};
    }
    工作表['!rows'][行号 - 1].hidden = true;
  } catch (错误) {
    throw new Error(`隐藏行失败: ${错误.message}`);
  }
}

/**
 * 隐藏列
 * @param {Object} 工作表 - 工作表对象
 * @param {number} 列号 - 要隐藏的列号（从1开始）
 */
function 隐藏列(工作表, 列号) {
  try {
    if (!工作表['!cols']) {
      工作表['!cols'] = [];
    }
    if (!工作表['!cols'][列号 - 1]) {
      工作表['!cols'][列号 - 1] = {};
    }
    工作表['!cols'][列号 - 1].hidden = true;
  } catch (错误) {
    throw new Error(`隐藏列失败: ${错误.message}`);
  }
}

/**
 * 保护工作表
 * @param {Object} 工作表 - 工作表对象
 * @param {string} 密码 - 保护密码
 * @param {Object} 选项 - 保护选项
 */
function 保护工作表(工作表, 密码 = '', 选项 = {}) {
  try {
    工作表['!protect'] = {
      password,
      ...选项
    };
  } catch (错误) {
    throw new Error(`保护工作表失败: ${错误.message}`);
  }
}

/**
 * 将工作簿转换为Base64字符串
 * @param {Object} 工作簿 - 工作簿对象
 * @param {string} 文件类型 - 文件类型
 * @returns {string} Base64编码的字符串
 */
function 工作簿转Base64(工作簿, 文件类型 = 'xlsx') {
  try {
    const 缓冲区 = 工作簿转Buffer(工作簿, { bookType: 文件类型 });
    return 缓冲区.toString('base64');
  } catch (错误) {
    throw new Error(`工作簿转Base64失败: ${错误.message}`);
  }
}

/**
 * 从Base64字符串读取Excel
 * @param {string} base64字符串 - Base64编码的Excel数据
 * @returns {Object} 工作簿对象
 */
function 从Base64读取Excel(base64字符串) {
  try {
    const 缓冲区 = Buffer.from(base64字符串, 'base64');
    return 读取Excel数据(缓冲区);
  } catch (错误) {
    throw new Error(`从Base64读取Excel失败: ${错误.message}`);
  }
}

/**
 * 对比两个工作表的差异
 * @param {Object} 工作表1 - 第一个工作表
 * @param {Object} 工作表2 - 第二个工作表
 * @returns {Array} 差异数组
 */
function 对比工作表差异(工作表1, 工作表2) {
  try {
    const 数据1 = 工作表转数组(工作表1);
    const 数据2 = 工作表转数组(工作表2);
    const 差异 = [];
    
    const 最大行数 = Math.max(数据1.length, 数据2.length);
    
    for (let 行 = 0; 行 < 最大行数; 行++) {
      const 行1 = 数据1[行] || [];
      const 行2 = 数据2[行] || [];
      const 最大列数 = Math.max(行1.length, 行2.length);
      
      for (let 列 = 0; 列 < 最大列数; 列++) {
        const 值1 = 行1[列] || '';
        const 值2 = 行2[列] || '';
        
        if (值1 !== 值2) {
          差异.push({
            单元格: 生成单元格地址(行, 列),
            原值: 值1,
            新值: 值2
          });
        }
      }
    }
    
    return 差异;
  } catch (错误) {
    throw new Error(`对比工作表差异失败: ${错误.message}`);
  }
}

/**
 * 批量替换单元格值
 * @param {Object} 工作表 - 工作表对象
 * @param {*} 查找值 - 要查找的值
 * @param {*} 替换值 - 要替换的值
 * @returns {number} 替换的单元格数量
 */
function 批量替换单元格(工作表, 查找值, 替换值) {
  try {
    let 替换计数 = 0;
    const 数组数据 = 工作表转数组(工作表);
    
    for (let 行 = 0; 行 < 数组数据.length; 行++) {
      for (let 列 = 0; 列 < 数组数据[行].length; 列++) {
        if (数组数据[行][列] === 查找值) {
          数组数据[行][列] = 替换值;
          替换计数++;
        }
      }
    }
    
    if (替换计数 > 0) {
      // 保留工作表属性
      const 合并信息 = 工作表['!merges'];
      const 列宽信息 = 工作表['!cols'];
      const 行高信息 = 工作表['!rows'];
      
      // 创建新工作表
      const 新工作表 = 数组转工作表(数组数据);
      
      // 恢复属性
      if (合并信息) 新工作表['!merges'] = 合并信息;
      if (列宽信息) 新工作表['!cols'] = 列宽信息;
      if (行高信息) 新工作表['!rows'] = 行高信息;
      
      // 复制回原工作表
      Object.keys(工作表).forEach(键 => {
        delete 工作表[键];
      });
      
      Object.keys(新工作表).forEach(键 => {
        工作表[键] = 新工作表[键];
      });
    }
    
    return 替换计数;
  } catch (错误) {
    throw new Error(`批量替换单元格失败: ${错误.message}`);
  }
}

module.exports = {
  // 核心函数
  读取Excel文件,
  读取Excel数据,
  创建工作簿,
  保存工作簿,
  工作簿转Buffer,
  工作簿转Base64,
  从Base64读取Excel,
  
  // 数据转换
  JSON转工作表,
  工作表转JSON,
  数组转工作表,
  工作表转数组,
  HTML转工作表,
  工作表转HTML,
  工作表转CSV,
  CSV转工作表,
  工作表转TSV,
  TSV转工作表,
  
  // 工作簿操作
  获取工作表名称列表,
  获取工作表,
  获取第一个工作表,
  添加工作表到工作簿,
  复制工作表,
  删除工作表,
  重命名工作表,
  克隆工作表,
  
  // 工作表操作
  创建工作表,
  清除工作表内容,
  设置单元格值,
  获取单元格值,
  设置单元格样式,
  合并单元格,
  设置列宽,
  设置行高,
  获取工作表范围,
  设置工作表范围,
  获取使用区域,
  创建带表头工作表,
  获取列标题,
  冻结窗格,
  自动调整列宽,
  设置页眉,
  设置页脚,
  隐藏行,
  隐藏列,
  保护工作表,
  
  // 行列操作
  插入行,
  删除行,
  插入列,
  删除列,
  追加数据到工作表,
  
  // 查找替换
  查找单元格,
  批量替换单元格,
  对比工作表差异,
  
  // 单元格地址操作
  解析单元格地址,
  生成单元格地址,
  解析范围,
  生成范围,
  
  // 高级操作
  读取所有工作表,
  保存多工作表Excel,
  导出到Excel,
  从Excel导入,
  是有效Excel文件,
  转换Excel格式,
  获取Excel文件信息,
  创建共享字符串表,
  
  // 获取原始模块
  获取原始XLSX: () => xlsx,
  
  // 常量
  文件类型: {
    XLSX: 'xlsx',
    XLSM: 'xlsm',
    XLS: 'xls',
    XLSB: 'xlsb',
    XLTX: 'xltx',
    XLTM: 'xltm',
    XLAM: 'xlam',
    XLA: 'xla',
    CSV: 'csv',
    TSV: 'tsv',
    HTML: 'html'
  },
  
  // 单元格类型
  单元格类型: {
    字符串: 's',
    数值: 'n',
    布尔值: 'b',
    日期: 'd',
    错误: 'e',
    空: 'z'
  }
};